<!-- MonacoEditor.vue -->
<template>
  <div 
    ref="editorContainer" 
    class="monaco-editor-container" 
    :style="{ height: height, width: '100%' }"
    :class="{ 'fullscreen-editor': isFullscreen }"
  >
    <div class="editor-header" v-if="showFullscreenBtn">
      <Icon 
        class="is-hover cursor-pointer" 
        :icon="isFullscreen ? 'radix-icons:exit-full-screen' : 'radix-icons:enter-full-screen'"
        color="var(--el-color-info)"
        hover-color="var(--el-color-primary)"
        @click="toggleFullscreen"
      />
    </div>
    <MonacoEditor
      ref="editorRef"
      :v-model:value="modelValue"
      v-bind="getBindValue"
      :language="language"
      :options="computedOptions"
      @change="handleEditorChange"
      :style="{ height: editorHeight }"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch, nextTick, useAttrs, computed } from 'vue'
import MonacoEditor from 'monaco-editor-vue3'
import Icon from '@/components/Icon/src/Icon.vue'

defineOptions({ name: 'MonacoEditor' })

const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  },
  language: {
    type: String,
    default: 'javascript'
  },
  height: {
    type: String,
    default: '200px'
  },
  options: {
    type: Object,
    default: () => ({
      automaticLayout: true,
      minimap: {
        enabled: true
      },
      scrollBeyondLastLine: false,
      readOnly: false
    })
  },
  showFullscreenBtn: {
    type: Boolean,
    default: true
  }
})

const getBindValue = computed(() => {
  const attrs = useAttrs()
  const obj = { ...attrs, ...props }
  return obj
})

const emit = defineEmits<{
  (e: 'update:modelValue', value: string): void
  (e: 'change', value: string): void
}>()

const handleEditorChange = (value) => {
  emit('update:modelValue', value)
  emit('change', value)
}

const editorContainer = ref()
const editorRef = ref()
const isFullscreen = ref(false)
const originalHeight = ref(props.height)
const originalPosition = ref('')

const computedOptions = computed(() => {
  return {
    ...props.options,
    automaticLayout: true
  }
})

const editorHeight = computed(() => {
  if (isFullscreen.value) {
    // 全屏时计算高度，减去header高度
    return 'calc(100vh - 40px)'
  }
  return props.height
})

const toggleFullscreen = () => {
  isFullscreen.value = !isFullscreen.value
  if (isFullscreen.value) {
    originalHeight.value = props.height
    originalPosition.value = document.body.style.position
    document.body.style.position = 'fixed'
  } else {
    document.body.style.position = originalPosition.value
  }
}

watch(isFullscreen, (newVal) => {
  // 切换全屏时，更新编辑器布局
  nextTick(() => {
    if (editorRef.value && editorRef.value.editor) {
      editorRef.value.editor.layout()
    }
  })
})

onMounted(() => {
  
})

onBeforeUnmount(() => {
  // 恢复body样式
  if (isFullscreen.value) {
    document.body.style.position = originalPosition.value
  }
  // editorRef.value.dispose()
})

// 暴露编辑器实例给父组件使用
defineExpose({
  editorRef,
  isFullscreen,
  toggleFullscreen
})
</script>

<style scoped>
.monaco-editor-container {
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  position: relative;
}

.monaco-editor-container.fullscreen-editor {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw !important;
  height: 100vh !important;
  z-index: 9999;
  border-radius: 0;
  border: none;
}

.editor-header {
  position: absolute;
  top: 5px;
  right: 5px;
  z-index: 10;
}

.monaco-editor-container :deep(.editor) {
  height: 100%;
}
</style>